#include <cmath>
#include "feature_extractor.h"

using namespace std;
using namespace stock_trade;

const int MAX_SITUATION_VALID_TIME = 5 * 60;
const int MAX_TRANSACTION_VALID_TIME = 60 * 60;

vector<float> FeatureExtractor::ExtractorRecent3PriceFeature(const vector<Transaction>& vecTransaction, Date date, Time time)
{
    vector<float> feature;
    float recentPrice = 0;
    float trend = 0;
    int loop = 0;
    for (int i = vecTransaction.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecTransaction[i].date != date)                                //不是当天的信息认为失效
            continue;
        if (time < vecTransaction[i].time)                                 //交易发生时间比评估时间晚
            continue;
        if (time - vecTransaction[i].time > MAX_TRANSACTION_VALID_TIME)    //超过30分钟认为信息失效
            break;
        if (abs(recentPrice - 0) < 0.00001)
        {
            recentPrice = vecTransaction[i].price; 
            continue;
        }
        loop++;
        if (loop > 3)                                                      //recent 3 price
            break;

        switch (loop)
        {
            case 1:
                if (vecTransaction[i].price > recentPrice)
                {
                    trend += 1;
                }
                if (vecTransaction[i].price < recentPrice)
                {
                    trend -= 1;
                }
                break;
            case 2:
                if (vecTransaction[i].price > recentPrice)
                {
                    trend += 2;
                }
                if (vecTransaction[i].price < recentPrice)
                {
                    trend -= 2;
                }
                break;
            case 3:
                if (vecTransaction[i].price > recentPrice)
                {
                    trend += 4;
                }
                if (vecTransaction[i].price < recentPrice)
                {
                    trend -= 4;
                }
                break;
        }
        recentPrice = vecTransaction[i].price;
    }
    feature.push_back(trend);
    return feature;
}

vector<float> FeatureExtractor::ExtractorRecent3ActionFeature(const vector<Transaction>& vecTransaction, Date date, Time time)
{
    vector<float> feature;
    float trend = 0;
    int loop = 0;
    for (int i = vecTransaction.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecTransaction[i].date != date)                                //不是当天的信息认为失效
            continue;
        if (time < vecTransaction[i].time)                                 //交易发生时间比评估时间晚
            continue;
        if (time - vecTransaction[i].time > MAX_TRANSACTION_VALID_TIME)    //超过30分钟认为信息失效
            break;
        //交易发生时间比评估时间早，且有效的最近的3个交易记录
        loop++;
        if (loop > 3)                                      //recent 3 price
            break;

        switch (loop)
        {
            case 1:
                if (vecTransaction[i].action == BUY)
                {
                    trend += 4;
                }
                else if (vecTransaction[i].action == SELL)
                {
                    trend -= 4;
                }
                break;
            case 2:
                if (vecTransaction[i].action == BUY)
                {
                    trend += 2;
                }
                else if (vecTransaction[i].action == SELL)
                {
                    trend -= 2;
                }
                break;
            case 3:
                if (vecTransaction[i].action == BUY)
                {
                    trend += 1;
                }
                else if (vecTransaction[i].action == SELL)
                {
                    trend -= 1;
                }
                break;
        }
    }
    feature.push_back(trend);
    return feature;
}

vector<float> FeatureExtractor::ExtractorRecent2QualityFeature(const vector<Transaction>& vecTransaction, Date date, Time time)
{
    vector<float> feature;
    float beforeDayQuality = 0;
    float before2DayQuality = 0;
    int beforeDayCount = 0;
    int before2DayCount = 0;
    //cout << "date1:" << date << endl;
    Date beforeDay = date;
    //cout << "date:" << date << endl;
    //cout << "beforeDay1:" << beforeDay << endl;
    Date before2Day = --date;
    //cout << "beforeDay:" << beforeDay << endl;
    //cout << "before2Day:" << before2Day << endl;
    for (int i = vecTransaction.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecTransaction[i].date == beforeDay && time < vecTransaction[i].time)                                //不是当天的信息认为失效
        {
            beforeDayQuality += vecTransaction[i].number * vecTransaction[i].price; 
            beforeDayCount++;
            continue;
        }
        if (vecTransaction[i].date == before2Day && time < vecTransaction[i].time)                                //不是当天的信息认为失效
        {
            before2DayQuality += vecTransaction[i].number * vecTransaction[i].price; 
            before2DayCount++;
            continue;
        }
    }
    float number = 0;
    if (abs(before2DayQuality - 0) > 0.00001 && abs(beforeDayQuality - 0) > 0.00001
            && beforeDayCount >= 50 && before2DayCount >= 50)
        number = beforeDayQuality / before2DayQuality;
    feature.push_back(number);
    //cout << "number " << number << endl;
    return feature;
}

vector<float> FeatureExtractor::ExtractorSituatuinFeature(const vector<Situation>& vecSituation, Date date, Time time)
{
    vector<float> feature;
    for (int i = vecSituation.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecSituation[i].date != date)                                //不是当天的信息认为失效
            continue;
        if (time < vecSituation[i].time)                                 //交易发生时间比评估时间晚
            continue;
        if (time - vecSituation[i].time > MAX_SITUATION_VALID_TIME)      //超过30分钟认为信息失效
            break;
        //交易发生时间比评估时间早，且有效的记录
        float quantityPercent = vecSituation[i].GetQuantityPercent();
        float powerPercent = vecSituation[i].GetPowerPercent();
        feature.push_back(quantityPercent);
        feature.push_back(powerPercent);
        break;
    }
    if (feature.size() != 2)
    {
        feature.push_back(1);
        feature.push_back(1);
    }
    return feature;
}

vector<float> FeatureExtractor::ExtractorRecentMinute3PriceFeature(const vector<Situation>& vecSituation, Date date, Time time)
{
    vector<float> feature;
    float recentPrice = 0;
    float trend = 0;
    int loop = 0;
    for (int i = vecSituation.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecSituation[i].date != date)                                //不是当天的信息认为失效
            continue;
        if (time < vecSituation[i].time)                                 //交易发生时间比评估时间晚
            continue;
        if (time - vecSituation[i].time > MAX_SITUATION_VALID_TIME)     //超过5分钟认为信息失效
            break;
        if (abs(recentPrice - 0) < 0.00001)
        {
            recentPrice = vecSituation[i].nowPrice; 
            continue;
        }
        loop++;
        if (loop > 3)                                                      //recent 3 nowPrice
            break;

        switch (loop)
        {
            case 1:
                if (vecSituation[i].nowPrice > recentPrice)
                {
                    trend += 1;
                }
                if (vecSituation[i].nowPrice < recentPrice)
                {
                    trend -= 1;
                }
                break;
            case 2:
                if (vecSituation[i].nowPrice > recentPrice)
                {
                    trend += 2;
                }
                if (vecSituation[i].nowPrice < recentPrice)
                {
                    trend -= 2;
                }
                break;
            case 3:
                if (vecSituation[i].nowPrice > recentPrice)
                {
                    trend += 4;
                }
                if (vecSituation[i].nowPrice < recentPrice)
                {
                    trend -= 4;
                }
                break;
        }
        recentPrice = vecSituation[i].nowPrice;
    }
    feature.push_back(trend);
    return feature;
}

vector<float> FeatureExtractor::GetNowPrice(const vector<Situation>& vecSituation, Date date, Time time)
{
    vector<float> feature;
    for (int i = vecSituation.size() - 1; i >= 0; --i)                       //时间从晚到早的遍历
    {
        if (vecSituation[i].date != date)                                //不是当天的信息认为失效
            continue;
        if (time < vecSituation[i].time)                                 //交易发生时间比评估时间晚
            continue;
        feature.push_back(vecSituation[i].nowPrice);
        break;
    }
    if (feature.size() == 0)
    {
        feature.push_back(-1);
    }
    return feature;
}

vector<float> FeatureExtractor::GetLongTimePrices(const vector<Situation>& vecSituation, Date date, Time time)
{
    const float MAX_PRICE = 10000000;
    vector<float> feature;
    float maxPrice = 0;
    float minPrice = MAX_PRICE;
    int goodSituationNumber = 0;
    for (int i = 0; i < vecSituation.size(); ++i)                       //时间从早到晚的遍历
    {
        if (vecSituation[i].date > date)                                //不是当天的信息认为失效
            break;
        if (vecSituation[i].date == date && vecSituation[i].time > time)                                 //交易发生时间比评估时间晚
            break;
        if (abs(vecSituation[i].nowPrice - 0) < 0.00001)
            continue;
        if (vecSituation[i].nowPrice > maxPrice)
            maxPrice = vecSituation[i].nowPrice;
        if (vecSituation[i].nowPrice < minPrice)
            minPrice = vecSituation[i].nowPrice;
        goodSituationNumber++;
    }
    if (goodSituationNumber < 1024)
    {
        feature.push_back(-1);
        feature.push_back(-1);
        return feature;
    }
    feature.push_back(maxPrice);
    if (abs(minPrice - MAX_PRICE) < 0.00001)
        feature.push_back(0);
    else
        feature.push_back(minPrice);
    return feature;
}

vector<float> FeatureExtractor::MergeFeature(const vector<Situation>& vecSituation, const vector<Transaction>& vecTransaction,
        const vector<Situation>& vecLongTimeSituation, const vector<Transaction>& vecLongTimeTransaction, Date date, Time time)
{
    vector<float> allFeature;
    vector<float> tmpFeature;
    tmpFeature = ExtractorRecent3PriceFeature(vecTransaction, date, time);
    //tmpFeature = ExtractorRecentMinute3PriceFeature(vecSituation, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());
    tmpFeature = ExtractorRecent3ActionFeature(vecTransaction, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());
    tmpFeature = ExtractorSituatuinFeature(vecSituation, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());
    tmpFeature = GetNowPrice(vecSituation, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());
    tmpFeature = GetLongTimePrices(vecLongTimeSituation, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());
    tmpFeature = ExtractorRecent2QualityFeature(vecLongTimeTransaction, date, time);
    allFeature.insert(allFeature.end(), tmpFeature.begin(), tmpFeature.end());

    //feature1: Recent3Price; feature2: Recent3Action; feature3: GetQuantityPercent; feature4: GetPowerPercent; feature5: GetNowPrice; feature6: maxPrice; feature7: minPrice; feature8: rateOfQuality
    return allFeature;
}
